﻿using System;
using BaseLibrary;

namespace CodeToAddresConverter
{
    //Одна строка с коммандой
    internal class Command
    {
        //Разбор строки сразу в конструкторе
        public Command(string s)
        {
            Spaces = "";
            Code = "";
            Param1 = "";
            Param2 = "";
            Param3 = "";
            Comment = "";
            Number = -1;
            int n = 0;
            while (n < s.Length && s[n].IsSpace())
                Spaces += s[n++];
            if (n == s.Length) return;
            while (n < s.Length && !s[n].IsSpace() && s[n] != ';')
                Code += s[n++];
            if (Code.Length > 0 && Code[Code.Length - 1] == ':')
                Function = Code.Substring(0, Code.Length - 1);

            while (n < s.Length && s[n].IsSpace())
                n++;
            while (n < s.Length && !s[n].IsSpace() && s[n] != ';' && s[n] != ',')
                Param1 += s[n++];

            while (n < s.Length && (s[n].IsSpace() || s[n] == ','))
                n++;
            while (n < s.Length && !s[n].IsSpace() && s[n] != ';' && s[n] != ',')
                Param2 += s[n++];

            while (n < s.Length && (s[n].IsSpace() || s[n] == ','))
                n++;
            while (n < s.Length && !s[n].IsSpace() && s[n] != ';')
                Param3 += s[n++];

            while (n < s.Length && s[n].IsSpace())
                n++;
            if (n < s.Length && s[n] == ';')
            {
                HasComment = true;
                n++;
                while (n < s.Length)
                    Comment += s[n++];
            }
        }

        //Пробелы в начале записи
        public string Spaces { get; private set; }
        //Имя функции
        public string Code { get; private set; }
        //Параметры
        public string Param1 { get; private set; }
        public string Param2 { get; private set; }
        public string Param3 { get; private set; }
        //Ссылки на функции
        public Label Label1 { get; set; }
        public Label Label2 { get; set; }
        public Label Label3 { get; set; }

        //Ссылки на переменные
        public Label Var1 { get; set; }
        public Label Var2 { get; set; }
        public Label Var3 { get; set; }

        //Комментарий
        public string Comment { get; private set; }
        //Содержит комментарий
        public bool HasComment { get; private set; }
        //Функция, которая начинается с этой строчки
        public string Function { get; set; }
        //Номер комманды по порядку выполнения
        public int Number { get; set; }
        //Следующая комманда
        public Command NextCommand { get; set; }

        //Запись 
        public string Write()
        {
            string res = Spaces + Code;
            if (!Code.IsEmpty())
                for (int i = 0; i < 4 - Code.Length; i++)
                    res += ' ';
            if (Label1 != null && Label1.Number < 0)
                throw new Exception(string.Format("Label '{0}' is unknown", Label1.Code));
            if (Label2 != null && Label2.Number < 0)
                throw new Exception(string.Format("Label '{0}' is unknown", Label2.Code));
            if (Label3 != null && Label3.Number < 0)
                throw new Exception(string.Format("Label '{0}' is unknown", Label3.Code));
            string par1 = Label1 == null ? Param1 : Label1.Number.ToString();
            string par2 = Label2 == null ? Param2 : Label2.Number.ToString();
            string par3 = Label3 == null ? Param3 : Label3.Number.ToString();

            par1 = Var1 == null ? par1 : "[" + Var1.Number.ToString() + "]";
            par2 = Var2 == null ? par2 : "[" + Var2.Number.ToString() + "]";
            par3 = Var3 == null ? par3 : "[" + Var3.Number.ToString() + "]";

            if (!Param1.IsEmpty())
                res += " " + par1;
            if (!Param2.IsEmpty())
                res += ", " + par2;
            if (!Param3.IsEmpty())
                res += ", " + par3;
            if (HasComment || NextCommand == null || !NextCommand.Code.IsEmpty() || !NextCommand.HasComment)
            {
                int spaces = 9 - par1.Length - par2.Length - par3.Length - Spaces.Length;
                if (!Param1.IsEmpty()) spaces--;
                if (!Param2.IsEmpty()) spaces--;
                if (!Param3.IsEmpty()) spaces--;
                spaces = Math.Max(1, spaces);
                if (!Code.IsEmpty())
                    for (int i = 0; i < spaces; i++)
                        res += ' ';
                if (HasComment || Number != -1 || !Function.IsEmpty()) res += ";";
                if (Number != -1) res += Number + ". ";
                if (!Function.IsEmpty()) res += ">" + Function + ". ";
                res += Comment;    
            }
            return res;
        }
    }
}
